package middleware

import (
	"fmt"
	"github.com/e421083458/golang_common/lib"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
	"tino_manager/public"
)

func JWTAuthMiddleware() func(c *gin.Context) {
	return func(c *gin.Context) {
		isMatched := false
		for _, url := range lib.GetStringSliceConf("base.http.no_jwt") {
			if c.Request.URL.Path == url {
				isMatched = true
			}
		}

		if isMatched {
			c.Next()
		} else {
			accept := c.Request.Header.Get("Accept")
			if accept == "text/event-stream" {
				//如果是event流
				w := c.Writer
				w.Header().Set("Content-Type", "text/event-stream")
				w.Header().Set("Cache-Control", "no-cache")
				w.Header().Set("Connection", "keep-alive")
				w.Header().Set("Transfer-Encoding", "chunked")
				f, _ := w.(http.Flusher)
				cookie := c.Request.Header.Get("Cookie")
				if cookie == "" {
					fmt.Fprintf(w, "event: error\n")
					fmt.Fprintf(w, "data: 身份验证失效\n\n")
					fmt.Fprintf(w, "event: disconnected\n")
					fmt.Fprintf(w, "data: disconnected\n\n")
					f.Flush()
					c.Abort()
					return
				}
				split := strings.SplitN(cookie, ";", 2)
				tokenIndex := -1
				for index, item := range split {
					hasIndex := strings.Index(item, "teacher_free")
					if hasIndex >= 0 {
						tokenIndex = index
					}
				}
				if tokenIndex == -1 {
					fmt.Fprintf(w, "event: error\n")
					fmt.Fprintf(w, "data: 身份验证失效\n\n")
					fmt.Fprintf(w, "event: disconnected\n")
					fmt.Fprintf(w, "data: disconnected\n\n")
					f.Flush()
					c.Abort()
					return
				}
				token := strings.SplitN(split[tokenIndex], "=", 2)
				mc, err := public.ParseToken(token[1])
				if err != nil {
					fmt.Fprintf(w, "event: error\n")
					fmt.Fprintf(w, "data: 身份验证失效\n\n")
					fmt.Fprintf(w, "event: disconnected\n")
					fmt.Fprintf(w, "data: disconnected\n\n")
					f.Flush()
					c.Abort()
					return
				}
				c.Set("userInfo", mc)
				c.Next()
			} else {
				//这里假设Token放在header的Authorization中并使用Bearer开头
				err := public.RequestValidateToken(c)
				if err != nil {
					ResponseError(c, 401, err, true)
					c.Abort()
					return
				}
				c.Next()
			}

		}

	}
}
